﻿using OpenApi.Configuration;
using System;
using System.Collections.Generic;
using System.Configuration;
using System.Linq;
using System.Reflection;
using System.ServiceModel;
using System.ServiceModel.Configuration;
using System.ServiceModel.Description;
using System.ServiceModel.Web;
using System.Text;
using System.Threading.Tasks;

namespace OpenApi
{
	/// <summary>
	/// 开放接口发布器。
	/// </summary>
	public class OpenApiPublisher
	{

		/// <summary>
		/// 从配置文件读取服务型并发布。
		/// </summary>
		public static void Publish()
		{
			OpenApiConfigurationSection section = OpenApiConfigurationSection.Root;
			List<ServiceInfo> serviceInfos = new List<ServiceInfo>();
			foreach (OpenApiServiceElement serviceElement in section.Services)
			{
				ServiceInfo serviceInfo = new ServiceInfo();
				serviceInfo.Name = serviceElement.Name;
				serviceInfo.Contract = Type.GetType(serviceElement.Contract);
				serviceInfo.ContractImpl = Type.GetType(serviceElement.ContractImpl);
				serviceInfos.Add(serviceInfo);
			}

			int port = section.Default.Port;
			IAuthProvider auth = null;
			if (!String.IsNullOrWhiteSpace(section.Default.AuthType))
			{
				auth = (IAuthProvider)Activator.CreateInstance(Type.GetType(section.Default.AuthType));
			}

			Publish(serviceInfos, port, auth);
		}

		/// <summary>
		/// 发布指定服务。
		/// </summary>
		/// <param name="serviceInfos"></param>
		public static void Publish(List<ServiceInfo> serviceInfos)
		{
			OpenApiConfigurationSection section = OpenApiConfigurationSection.Root;

			int port = section.Default.Port;
			IAuthProvider auth = null;
			if (!String.IsNullOrWhiteSpace(section.Default.AuthType))
			{
				auth = (IAuthProvider)Activator.CreateInstance(Type.GetType(section.Default.AuthType));
			}

			Publish(serviceInfos, port, auth);
		}

		/// <summary>
		/// 发布制定服务。
		/// </summary>
		/// <param name="serviceInfos"></param>
		/// <param name="port"></param>
		/// <param name="auth"></param>
		public static void Publish(List<ServiceInfo> serviceInfos, int port, IAuthProvider auth)
		{
			Uri baseUri = new Uri("http://localhost:" + port);
			WebHttpBinding webHttpBinding = new WebHttpBinding();
			WebHttpBehavior webHttpBehavior = new WebHttpBehavior();
			webHttpBehavior.DefaultOutgoingResponseFormat = WebMessageFormat.Json;
			webHttpBehavior.HelpEnabled = true;
			AuthEndpointBehavior authBehavior = new AuthEndpointBehavior(auth);

			foreach (var serviceInfo in serviceInfos)
			{
				WebServiceHost host = new WebServiceHost(serviceInfo.ContractImpl, baseUri);
				ServiceEndpoint ep = host.AddServiceEndpoint(serviceInfo.Contract, webHttpBinding, serviceInfo.Name);
				ep.EndpointBehaviors.Add(webHttpBehavior);
				ep.EndpointBehaviors.Add(authBehavior);
				host.Open();
			}

			MyLogger.Info(baseUri);
		}
	}
}
